#ifndef _USBKEY_H__
#define _USBKEY_H__


/* USB Token values */
#define USB_PID_OUT    0xE1
#define USB_PID_IN     0x69
#define USB_PID_SOF    0xA5
#define USB_PID_SETUP  0x2D

#define USB_PID_PRE    0x3C

#define USB_PID_DATA0  0xC3
#define USB_PID_DATA1  0x4B

#define USB_PID_ACK    0xD2
#define USB_PID_NACK   0x5A
#define USB_PID_STALL  0x1E

/* USB direction values: */
#define USBRQ_DIR_MASK              0x80
#define USBRQ_DIR_HOST_TO_DEVICE    (0<<7)
#define USBRQ_DIR_DEVICE_TO_HOST    (1<<7)
#define USBRQ_DIR_DEVICE_TO_HOST_INTERFACE 0x01
#define USBRQ_DIR_DEVICE_TO_HOST_ENDPOINT  0x02

/* USB Standard Requests */
#define USBRQ_GET_STATUS              0
#define USBRQ_CLEAR_FEATURE           1
#define USBRQ_SET_FEATURE             3
#define USBRQ_SET_ADDRESS             5
#define USBRQ_GET_DESCRIPTOR          6
#define USBRQ_SET_DESCRIPTOR          7
#define USBRQ_GET_CONFIGURATION       8
#define USBRQ_SET_CONFIGURATION       9
#define USBRQ_GET_INTERFACE          10
#define USBRQ_SET_INTERFACE          11
#define USBRQ_SYNCH_FRAME            12

/* USB descriptor constants */
#define USB_DESCRIPTOR_DEVICE                         1
#define USB_DESCRIPTOR_CONFIGURATION                  2
#define USB_DESCRIPTOR_STRING                         3
#define USB_DESCRIPTOR_INTERFACE                      4
#define USB_DESCRIPTOR_ENDPOINT                       5
#define USB_DESCRIPTOR_DEVICE_QUALIFIER               6
#define USB_DESCRIPTOR_OTHER_SPEED_CONFIGURATION      7
#define USB_DESCRIPTOR_INTERFACE_POWER1               8
#define USB_DESCRIPTOR_HID                         0x21
#define USB_DESCRIPTOR_HID_REPORT                  0x22
#define USB_DESCRIPTOR_HID_PHYS                    0x23

/* USB HID Requests */
#define USBRQ_HID_GET_REPORT    0x01
#define USBRQ_HID_GET_IDLE      0x02
#define USBRQ_HID_GET_PROTOCOL  0x03
#define USBRQ_HID_SET_REPORT    0x09
#define USBRQ_HID_SET_IDLE      0x0a
#define USBRQ_HID_SET_PROTOCOL  0x0b

//https://blog.csdn.net/u014980289/article/details/62417601

//STEP 1
//reset
//setup
//Host -- > Device
//USBbmRequestType = 0x80    Get_Configuaration
//USBbRequest = 0x06         Get_Descriptor
//USBwValue = 0x01           Device Descriptor
//USBwIndex = 0x00
//USBwLength = 0x40          Max Bytes
//Device -- > Host
//HIDKEY_DevDesc[18]
/*Standard Device Descriptor*/
s8 HIDKEY_DevDesc[18] = {
    0x12,                /*bLength,Device Descriptor 18 bytes*/
    0x01,                /*bDescriptorType,01--Device Descriptor*/
    0x10,0x01,           /*bcdUSB,0110--USB 1.1*/
    0x00,                /*bDeviceClass,00-Device*/
    0x00,                /*bDeviceSubClass,00*/
    0x00,                /*bDeviceProtocol,00*/
    0x08,                /*bMaxPacketSize0,8*/
    0x83,0x04,           /*dVendor*/
    0x10,0x57,           /*idProduct*/
    0x10,0x01,           /*bcdDevice Ver-1.10*/
    0x01,                /*index of string descriptor describing Manufacturer--iManufacturer*/
    0x02,                /*index of string descriptor describing Product--iProduct*/
    0x03,                /*index of string descriptor describing SerialNumber--iSerialNumber*/
    0x01                 /*bNumConfigurations*/
    };

//STEP 2
//reset
//setup
//Host -- > Device
//USBbmRequestType = 0x00    Set_Address
//USBbRequest = 0x05
//USBwValue = 0x0004         Address = 0x04
//USBwIndex = 0x00
//USBwLength = 0x00
//ACK & empty packet


//STEP 3
//setup
//Host -- > Device
//USBbmRequestType = 0x80    Get_Configuaration
//USBbRequest = 0x06		   Get_Descriptor
//USBwValue = 0x01 		   Device Descriptor
//USBwIndex = 0x00
//USBwLength = 0x12
//Device -- > Host
//HIDKEY_DevDesc[18]

//STEP 4
//setup
//Host -- > Device
//USBbmRequestType = 0x80    Get_Configuaration
//USBbRequest = 0x06 		   Get_Descriptor
//USBwValue = 0x02           Configuaration + Interface + String + Endpoint Descriptor
//USBwIndex = 0x00
//USBwLength = 0xff
//Device -- > Host
//HIDKEY_CfgDesc[41]
s8 HIDKEY_CfgDesc[41] =
{
    0x09,                /*bLength,Configuration Descriptor 9 bytes*/
    0x02,                /*bDescriptorType,02--Configuration Descriptor*/
    0x29,0x00,           /*wTotalLength,41 bytes*/
    0x01,                /*bNumInterfaces*/
    0x01,                /*bConfigurationValue*/
    0x00,                /*iConfiguration*/
    0x80,                /*bmAttributes,Bit7-Bus power Bit6-Self power Bit5-Remote wakeup*/
    0x32,                /*MaxPower,*2mA*/
    //
    0x09,                /*bLength,Interface Descriptor 9 bytes*/
    0x04,                /*bDescriptorType,04--Interface Descriptor*/
    0x00,                /*bInterfaceNumber*/
    0x00,                /*bAlternateSetting*/
    0x02,                /*bNumEndpoints*/
    0x03,                /*bInterfaceClass,03-HID*/
    0x01,                /*bInterfaceSubClass,00-no boot 01-boot*/
    0x01,                /*bInterfaceProtocol,0-no 1-keyboard 02-mouse*/
    0x00,                /*iInterface*/
    //
    0x09,                /*bLength,HID Descriptor 9 bytes*/
    0x21,                /*bDescriptorType,21--HID Descriptor*/
    0x00,0x01,           /*bcdHID,0100--Ver1.00*/
    0x00,                /*bCountryCode*/
    0x01,                /*bNumDescriptors*/
    0x22,                /*bDescriptorType,22--HID REPORT DESC*/
    0x3d,0x00,           /*wDescriptorLength,Report Descritor length*/
    //
    0x07,                /*bLength,Endpoint Descriptor 7 bytes*/
    0x05,                /*bDescriptorType,05--Endpoint Descriptor*/
    0x81,                /*bEndpointAddress,bit7(0-OUT 1-IN);bit3:0 the endpoint numer*/
    0x03,                /*bmAttributes,03-Interrupt endpoint(00-control 01--isochronous 10-bulk 11-interrupt)*/
    0x08,0x00,           /*bMaxPacketSize0,8*/
    0x20,                /*bInterval,*1ms*/
    //
    0x07,                /*bLength,Endpoint Descriptor 7 bytes*/
    0x05,                /*bDescriptorType,05--Endpoint Descriptor*/
    0x01,                /*bEndpointAddress,bit7(0-OUT 1-IN);bit3:0 the endpoint numer*/
    0x03,                /*bmAttributes,03-Interrupt endpoint(00-control 01--isochronous 10-bulk 11-interrupt)*/
    0x01,0x00,           /*bMaxPacketSize0,1*/
    0x20                 /*bInterval,*1ms*/
};

//STEP 5
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x6
//USBwValue = 0x0300         03:String_descripotr 00:Index
//USBwIndex = 0x00
//USBwLength = 0xff
//Device -- > Host
//HIDKEY_StringLangID[4]
s8 HIDKEY_StringLangID[4] =
{
    0x04,                /*bLength,String Descriptor 4 bytes*/
    0x03,                /*bDescriptorType,03--String Descriptor*/
    0x09,0x04  //0409--US English
};

//STEP 6
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x0302          03:String_descripotr 02:Index
//USBwIndex = 0x0409
//USBwLength = 0xff
//Device -- > Host
//HIDKEY_StringProduct[32]
//unicode
s8 HIDKEY_StringProduct[] =
{
    0x22,
    0x03,
    'P', 0,
    'S', 0,
    ' ', 0,
    'U', 0,
    'S', 0,
    'B', 0,
    ' ', 0,
    'H', 0,
    'I', 0,
    'D', 0,
    'K', 0,
    'E', 0,
    'Y', 0,
    '-', 0,
    '0', 0,
    '1', 0
};

//STEP 7
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x0303          03:String_descripotr 03:Index
//USBwIndex = 0x0409
//USBwLength = 0xff
//Device -- > Host
//HIDKEY_StringSerial[]
//length error?
s8 HIDKEY_StringSerial[] =
{
    0x1E,
    0x03,
    'P', 0,
    'S', 0,
    ' ', 0,
    'U', 0,
    'S', 0,
    'B', 0,
    '-', 0,
    '0', 0,
    '0', 0,
    '0', 0, //6
    '0', 0, //5
    '0', 0, //5
    '0', 0, //3
    '1', 0  //6
};

//STEP 8
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x06
//USBwIndex = 0x00
//USBwLength = 0xa
//Dont support,STALL


//STEP 9
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x01
//USBwIndex = 0x00
//USBwLength = 0x12
//Device -- > Host
//HIDKEY_DevDesc[18]

//STEP 10
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x02
//USBwIndex = 0x00
//USBwLength = 0x09
//Device -- > Host
//HIDKEY_CfgDesc[] first 9 bytes

//STEP 11
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x02
//USBwIndex = 0x00
//USBwLength = 0x29
//Device -- > Host
//HIDKEY_CfgDesc[41]

//STEP 12
//setup
//Host -- > Device
//USBbmRequestType = 0x00
//USBbRequest = 0x09            set_configuration
//USBwValue = 0x0001            select configuration
//USBwIndex = 0x00              set current configuration = 0x01
//USBwLength = 0x00
//ACK&empty packet

//STEP 13
//setup
//Host -- > Device
//USBbmRequestType = 0x21       HID
//USBbRequest = 0x0a            set_idle
//USBwValue = 0x00
//USBwIndex = 0x00
//USBwLength = 0x00
//ACK&empty packet

//STEP 14
//setup
//Host -- > Device
//USBbmRequestType = 0x81      Interface_request
//USBbRequest = 0x06
//USBwValue = 0x22             Report_descriptor
//USBwIndex = 0x00
//USBwLength = 0x7d
//Device -- > Host
//HIDKEY_KeyRepDesc[]
s8 HIDKEY_KeyRepDesc[] =
{
	0x05, 0x01, // USAGE_PAGE (Generic Desktop)
	0x09, 0x06, // USAGE (Keyboard)
	0xa1, 0x01, // COLLECTION (Application)
	0x05, 0x07, //     USAGE_PAGE (Keyboard/Keypad)

    //1--the first byte(L/R ctrl,alt,shift,win)
	0x19, 0xe0, //     USAGE_MINIMUM (Keyboard LeftControl)
	0x29, 0xe7, //     USAGE_MAXIMUM (Keyboard Right GUI)
	0x15, 0x00, //     LOGICAL_MINIMUM (0)
	0x25, 0x01, //     LOGICAL_MAXIMUM (1)
	0x95, 0x08, //     REPORT_COUNT (8)
	0x75, 0x01, //     REPORT_SIZE (1)
	0x81, 0x02, //     INPUT (Data,Var,Abs)

	//2--the sencond byte is reserved,so it's const(Cnst)
	0x95, 0x01, //     REPORT_COUNT (1)
	0x75, 0x08, //     REPORT_SIZE (8)
	0x81, 0x03, //     INPUT (Cnst,Var,Abs)

	//3--six bytes
	//bug?-0x15,0x00,//LOGICAL_MINIMUM (0)
	0x95, 0x06, //   REPORT_COUNT (6)
	0x75, 0x08, //   REPORT_SIZE (8)
	0x25, 0xFF, //   LOGICAL_MAXIMUM (255)
	0x19, 0x00, //   USAGE_MINIMUM (Reserved (no event indicated))
	0x29, 0x65, //   USAGE_MAXIMUM (Keyboard Application)
	0x81, 0x00, //   INPUT (Data,Ary,Abs)

    //4--the output byte,LED,5 bits(1-5)
	0x25, 0x01, //   LOGICAL_MAXIMUM (1)
	0x95, 0x05, //   REPORT_COUNT (5)
	0x75, 0x01, //   REPORT_SIZE (1)
	0x05, 0x08, //   USAGE_PAGE (LEDs)
	0x19, 0x01, //   USAGE_MINIMUM (Num Lock)
	0x29, 0x05, //   USAGE_MAXIMUM (Kana)
	0x91, 0x02, //   OUTPUT (Data,Var,Abs)

	//5--the output byte,the other 3 bits
	0x95, 0x01, //   REPORT_COUNT (1)
	0x75, 0x03, //   REPORT_SIZE (3)
	0x91, 0x03, //   OUTPUT (Cnst,Var,Abs)

	0xC0        //   END_COLLECTION
};

//STEP 15
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x0301
//USBwIndex = 0x0409
//USBwLength = 0xff
//Device -- > Host
///*iManufacturer*/
s8 HIDKEY_StringManufacturer[] =
{
    0x10,
    0x03,
    'T', 0,
    'h', 0,
    'e', 0,
    'W', 0,
    'o', 0,
    'r', 0,
    'k', 0
};



//STEP 16
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x0303
//USBwIndex = 0x0409
//USBwLength = 0xff
//Device -- > Host
//HIDKEY_StringSerial[]

//STEP 17
//setup
//Host -- > Device
//USBbmRequestType = 0x21
//USBbRequest = 0x0a
//USBwValue = 0x00
//USBwIndex = 0x00
//USBwLength = 0x00

//STEP 18
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x06
//USBwIndex = 0x00
//USBwLength = 0x0a
//Dont support,STALL

//STEP 19
//setup
//Host -- > Device
//USBbmRequestType = 0x21
//USBbRequest = 0x0a
//USBwValue = 0x00
//USBwIndex = 0x00
//USBwLength = 0x00

//STEP 20
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x0301
//USBwIndex = 0x0409
//USBwLength = 0xff
//Device -- > Host
///*iManufacturer*/

//STEP 21
//setup
//Host -- > Device
//USBbmRequestType = 0x80
//USBbRequest = 0x06
//USBwValue = 0x0303
//USBwIndex = 0x0409
//USBwLength = 0xff
//Device -- > Host
//HIDKEY_StringSerial[]

//STEP 22
//setup
//Host -- > Device
//USBbmRequestType = 0x21
//USBbRequest = 0x0a
//USBwValue = 0x00
//USBwIndex = 0x00
//USBwLength = 0x00

#endif
